package cn.tedu._03vehicle.base.interceptors;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 限流拦截器:60秒之内同一个IP地址访问网站次数不能超过3次;
 */

public class RateLimitInterceptor implements HandlerInterceptor {
    private static final int MAX_REQUESTS_PER_MINUTE = 3;
    private static final int WINDOW_SIZE_SECONDS = 60; //时间窗口大小

    //{"192.168.1.11": 1, "192.168.1.12": 3, ...}
    private final ConcurrentHashMap<String, Integer> clientCounts = new ConcurrentHashMap<>();
    //{"192.168.1.11": "2025-03-10 17:50:00", "192.168.1.12":"2025-03-10 01:10:30"}
    private final ConcurrentHashMap<String, LocalDateTime> lastResetTimes = new ConcurrentHashMap<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String remoteAddr = request.getRemoteAddr(); //192.168.1.11
        LocalDateTime lastTime = lastResetTimes.get(remoteAddr); //2025-03-10 00:00:00 || null
        //该IP第1次访问网站 或者  距离上一次访问已经超过了60秒的情况; 计算器清零,访问时间也要更新;
        if (lastTime==null || LocalDateTime.now().isAfter(lastTime.plusSeconds(WINDOW_SIZE_SECONDS))){
            clientCounts.put(remoteAddr, 0);
            lastResetTimes.put(remoteAddr, LocalDateTime.now());
        }
        //非第1次访问,并且距离上次访问在60秒以内;
        //计数器+1,时间不动;
        int count = clientCounts.merge(remoteAddr, 1, Integer::sum);

        //检查是否查过限制
        if (count > MAX_REQUESTS_PER_MINUTE) {
            throw new RuntimeException("访问过于频繁,请稍后再试~~");
        }

        //放行
        return true;
    }
}













